package com.stone.starter.core.util.list;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

import static com.stone.starter.core.util.string.StringUtil.strFormat;

/**
 * list集合工具类
 *
 * @author Mr_wenpan@163.com 2021/8/5 11:07 下午
 */
public class ListUtil {
    /**
     * logger
     */
    private static final Logger LOG = LoggerFactory.getLogger(ListUtil.class);

    /**
     * 判断数组是否为空，并且打印判断结果
     *
     * @param list   集合数据
     * @param msgT   提示消息
     * @param params 提示消息参数
     * @return boolean
     * @author Mr_wenpan@163.com 2019-12-25 5:14 PM
     */
    public static boolean listIsEmpty(Logger logger, List list, String msgT, Object... params) {
        boolean res = CollectionUtils.isEmpty(list);
        if (null == logger) {
            LOG.info(strFormat(msgT, params) + " :[{}]", res);
        } else {
            logger.info(strFormat(msgT, params) + " :[{}]", res);
        }
        return res;
    }

    /**
     * 判断数组是否为空，并且打印判断结果
     *
     * @param list   集合数据
     * @param msgT   提示消息
     * @param params 提示消息参数
     * @return boolean
     * @author Mr_wenpan@163.com 2019-12-25 5:14 PM
     */
    public static boolean listIsEmpty(List list, String msgT, Object... params) {
        return listIsEmpty(null, list, msgT, params);
    }

    /**
     * 判断数组是否不为空，并且打印判断结果
     *
     * @param list   集合数据
     * @param msgT   提示消息
     * @param params 提示消息参数
     * @return boolean
     * @author Mr_wenpan@163.com 2019-12-25 5:14 PM
     */
    public static boolean listIsNotEmpty(Logger logger, List list, String msgT, Object... params) {
        boolean res = CollectionUtils.isNotEmpty(list);
        if (null == logger) {
            LOG.info(strFormat(msgT, params) + " :[{}]", res);
        } else {
            logger.info(strFormat(msgT, params) + " :[{}]", res);
        }
        return res;
    }

    /**
     * 判断数组是否不为空，并且打印判断结果
     *
     * @param list   集合数据
     * @param msgT   提示消息
     * @param params 提示消息参数
     * @return boolean
     * @author Mr_wenpan@163.com 2019-12-25 5:14 PM
     */
    public static boolean listIsNotEmpty(List list, String msgT, Object... params) {
        return listIsNotEmpty(null, list, msgT, params);
    }


    /**
     * 按指定大小，分隔集合List，将集合按规定个数分为n个部分
     *
     * @param sourceList  原集合大小
     * @param perListSize 拆分后期望的每个集合的数据大小
     * @return 子List集合
     */
    public static <T> List<List<T>> splitList(List<T> sourceList, int perListSize) {
        if (sourceList == null || sourceList.size() == 0 || perListSize < 1) {
            return null;
        }

        List<List<T>> result = new ArrayList<>();

        int size = sourceList.size();
        int count = (size + perListSize - 1) / perListSize;

        for (int i = 0; i < count; i++) {
            List<T> subList = sourceList.subList(i * perListSize, (Math.min((i + 1) * perListSize, size)));
            result.add(subList);
        }
        return result;
    }

    /**
     * 将一个list均分成n个子list, 主要通过偏移量来实现
     *
     * @param source 原集合
     * @param n      均分成多少个集合
     * @return 子List集合
     */
    public static <T> List<List<T>> averageAssign(List<T> source, int n) {
        List<List<T>> result = new ArrayList<>();
        // (先计算出余数)
        int remaider = source.size() % n;
        // 然后是商
        int number = source.size() / n;
        // 偏移量
        int offset = 0;
        for (int i = 0; i < n; i++) {
            List<T> value;
            if (remaider > 0) {
                value = source.subList(i * number + offset, (i + 1) * number + offset + 1);
                remaider--;
                offset++;
            } else {
                value = source.subList(i * number + offset, (i + 1) * number + offset);
            }
            result.add(value);
        }
        return result;
    }

    /**
     * 按自定义规则分离list集合数据
     *
     * @param dataList list集合数据
     * @return ImmutablePair<java.util.List < T>,java.util.List<T>>
     * @author Mr_wenpan@163.com 2021/8/5 11:02 下午
     */
    public static <T> ImmutablePair<List<T>, List<T>> splitList(List<T> dataList, Predicate<T> predicate) {
        if (CollectionUtils.isEmpty(dataList)) {
            return ImmutablePair.nullPair();
        }
        List<T> errorList = new ArrayList<>();
        List<T> correctList = new ArrayList<>();
        for (T data : dataList) {
            if (predicate.test(data)) {
                correctList.add(data);
                continue;
            }
            errorList.add(data);
        }
        return ImmutablePair.of(correctList, errorList);
    }

}